/*
 * ModeleImage.java
 *
 * Created on 18 novembre 2007, 18:00
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package Modele;

import java.awt.Graphics;
import java.awt.color.ColorSpace;
import javax.imageio.ImageIO;

import java.io.File;
import java.io.IOException;

import java.awt.image.BufferedImage;

import java.awt.geom.AffineTransform;
import java.awt.image.ByteLookupTable;
import java.awt.image.LookupOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.awt.image.AffineTransformOp;
import java.awt.image.ColorConvertOp;
import java.util.Observable;


/**
 *
 * @author Soufiane GARCH
 * If you want to change anything in this source, please contact me
 */
public class ModeleImage extends Observable{
   
    private String nom;
    private String chemin;
    private String extention;
    private String adresse;
    private transient String legende;
    private transient int largeur;
    private transient int hauteur;
    private transient long taille;
    private transient BufferedImage image;
    private File file;

    
    
    /**
     * 
     * Creates a new instance of ModeleImage
     * 
     * @param File file
     */
    public ModeleImage(File file) {
        this.file = file;
        initialize(this.file);
        this.legende = "";
    }
    
    /**
     * 
     * Creates a new instance of ModeleImage
     * 
     * @param String adresse
     */
    public ModeleImage(String adresse) {
        this.file = new File(adresse);
        initialize(this.file);
        this.legende = "";
    }

    /* Les Seteurs */
    
    /**
     *Set the extention of picture
     *@return void
     */
    public void setExtention(String nom){
        int Index = nom.lastIndexOf('.');
        if (Index < 0)
            this.extention = "";
        else this.extention = nom.substring(Index + 1);
    }
    
    /**
     *Set the nom of picture
     *@return void
     */
    public void setNom(String nom){
        int Index = nom.lastIndexOf('.');
        if (Index > 0)
            this.nom = nom.substring(0, Index);
        else this.nom = nom;
    }
    
    /**
     *Set the adresse of picture
     *@return void
     */
    public void setChemin(String chemin){
        this.chemin = chemin;
    }
    
     /**
     *Set the legende of picture
     *@return void
     */
    public void setLegende(String legende){
        this.legende = legende;
    }

    /**Set the width of picture
     *
     *@return void
     */
    public void setLargeur(int largeur){
        this.largeur = largeur;
    }
    
     /**Set the height of picture
     *
     *@return void
     */
    public void setHauteur(int hauteur){
        this.hauteur = hauteur;
    }
    
     /**Set the width and height of picture
     *
     * @param int Largeur
     * @param int Hauteur
     * @return void
     */
    public void setDimension(int Largeur, int hauteur){
        this.largeur = Largeur;
        this.hauteur = hauteur;
    }    
    
     /**Set the size of picture
     *
     *@return void
     */
    public void setTaille(long taille){
        this.taille = taille;
    }
    
     /**Set the image of picture
     *
     *@return void
     */
    public void setImage(File file){
        try{
            image = ImageIO.read(file);
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }
    /** Set the source of picture
     *
     *@return void
     */
    public void setFile(File file){
        this.file = file;
    }
    
    /* Les Geteurs */
    
    /**
     *Get the nom of picture
     *@return String
     */
    public String getNom(){
        return this.nom;
    }
    
    /**
     *Get the path that contains the picture
     *@return String
     */
    public String getChemin(){
        return this.chemin;
    }
    
    /**
     *Get the extention of picture
     *@return String
     */
    public String getExtention(){
        return this.extention;
    }
    
     /**
     *Get the adress of picture
     *adress = chemin\nom.extention
     *@return String
     */
    public String getAdresse(){
        String adr = "";
        File[] racine = File.listRoots();
        adr = this.chemin;
        
        if (racine[0].toString() != "/")
            adr += "\\"+ this.nom;
        else 
            adr += "/"+ this.nom;
        
        if (this.extention != "")
                adr +=  "." + this.extention;
        return adr;
    }
    
     /**
     *Get the legende of picture
     *@return String
     */
    public String getLegende(){
        return this.legende;
    }
    
    /**Get the width of picture
     *
     *@return int
     */
    public int getLargeur(){
        return this.largeur;
    }
    
     /**Get the height of picture
     *
     *@return int
     */
    public int getHauteur(){
        return this.hauteur;
    }
    
     /**Get the size of picture
     *
     *@return long
     */
    public long getTaille(){
        return this.taille;
    }

     /**Get the image of picture
     *
     *@return BufferedImage
     */
    public BufferedImage getImage(){
        return this.image;
    }
    
    /**
     *Get file of picture
     *
     *@return File
     */
    public File getFile(){
        return this.file;
    }
    
    
    public void setAdresse(String adr){
        this.adresse = adr;
    }
    /**
    *Initialize a width, height and size of picture
    *
    *@return void
    */
    public void initialize(File file){
        setImage(file);
        setNom(file.getName());
        setChemin(file.getParent());
        setExtention(file.getName());
        setAdresse(file.getAbsolutePath());
        setLargeur(image.getWidth(null));
        setHauteur(image.getHeight(null));
        setTaille(file.length());
    }

    /**
     *Set a new width and height of picture according to the chosen criterion 
     * 1 for a percentage 
     * 2 for following the pixels
     */
    public void redimensionnerImage(int largeur, int hauteur, int critere){
        switch(critere){
            case 1: 
                setDimension(getLargeur() * largeur, getHauteur() * hauteur);
                break;
                
            case 2:
                setDimension(largeur, hauteur);
                break;
        }
        
        
    }
    
    /**
     *Save the modifications (Width, Heigth) and set the new caracteristique of picture
     *La fonction ne marche pas encore, pourquoi? je ne sais pas.
     *@return void
     */
    public void enregistrerModificaions(String adr) throws IOException{
        
        File out = new File(adr);
        
        Graphics g = image.createGraphics();
        g.drawImage(image,0,0,image.getWidth(), image.getHeight(), null);
        
 
        ImageIO.write(image, this.getExtention().toUpperCase(), out);
        
        
        
        
        
        
        /*if (file.canWrite() != true) throw new IOException();
        
        OutputStream out = null;
        
        try{
            out = new FileOutputStream(new File(chemin + "\\10.jpg"));
        }catch(IOException ioe1){
            ioe1.printStackTrace();
        }
        try{
            ImageIO.write(this.image, this.extention, out);
        }
        catch(IOException ioe2){
            ioe2.printStackTrace();
        }
        
        try {
		out.flush();
	} catch (IOException ioe3) {
          	ioe3.printStackTrace();
	}
	try {
		out.close();
	} catch (IOException ioe4) {
		ioe4.printStackTrace();
	}*/
    }
    
    /**
     *Rotation de l'image suivant un angle
     *
     *@param int Angle de rotation en degre
     *
     *@return void
     */
    public void rotation(int angle){
        AffineTransform transform = AffineTransform.getRotateInstance(Math.toRadians(angle), image.getWidth() / 2, image.getHeight() / 2);
	AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
        BufferedImage filteredImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
	op.filter(image, filteredImage);
	image = filteredImage;
    }
    
     /**Ajoute un flou doux � l'image
     *
     *@param void
     *
     *@return void
     */ 
    public void flou() {
        float weight = 1.0f / 9.0f;
        float[] elements = new float[9];
        for (int i = 0; i < 9; i++)
        elements[i] = weight;
        Kernel kernel = new Kernel(3, 3, elements);
        ConvolveOp op = new ConvolveOp(kernel);
        BufferedImage filteredImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
	op.filter(image, filteredImage);
	image = filteredImage;
    }
    
    /**
     *Trnasforme l'image en negative
     *
     *@param void
     *
     *@return void
     */
    public void negative(){
        byte negative[] = new byte[256];
	for (int i = 0; i < 256; i++)
            negative[i] = (byte) (255 - i);
	ByteLookupTable table = new ByteLookupTable(0, negative);
	LookupOp op = new LookupOp(table, null);
        BufferedImage filteredImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
	op.filter(image, filteredImage);
	image = filteredImage;        
    }
    
    public void zoom(){
        double scaleValue = 1.5;
        int largeurTmp = (int) (image.getWidth() * scaleValue);
        int hauteurTmp = (int) (image.getHeight() * scaleValue);
        if ( (largeurTmp > 2000) || (hauteurTmp > 2000) )
            return;
        largeur = largeurTmp;
        hauteur = hauteurTmp;
        AffineTransform tx = new AffineTransform();
        tx.scale(scaleValue, scaleValue);
        AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
        BufferedImage biNew = new BufferedImage( (int) (image.getWidth() * scaleValue), (int) (image.getHeight() * scaleValue), image.getType());
        image = op.filter(image, biNew);
    }
    
    public void dezoom(){
        double scaleValue = 0.5;
        int largeurTmp = (int) (image.getWidth() * scaleValue);
        int hauteurTmp = (int) (image.getHeight() * scaleValue);
        if ( (largeurTmp < 10) || (hauteurTmp < 10) )
            return;
        largeur = largeurTmp;
        hauteur = hauteurTmp;
        AffineTransform tx = new AffineTransform();
        tx.scale(scaleValue, scaleValue);
        AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
        BufferedImage biNew = new BufferedImage( (int) (image.getWidth() * scaleValue), (int) (image.getHeight() * scaleValue), image.getType());
        image = op.filter(image, biNew);
    }
    
    public void gris(){
        ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
        image = op.filter(image,null);
    }
    
    private void convolve(float[] elements) {
	Kernel kernel = new Kernel(3, 3, elements);
	ConvolveOp op = new ConvolveOp(kernel);
	BufferedImage filteredImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
	image = op.filter(image, filteredImage);
    }
    
    public void sharpen() {
	float[] elements = { 0.0f, -1.0f, 0.0f,
                             -1.0f, 5.0f, -1.0f,
                              0.0f, -1.0f, 0.0f };
	convolve(elements);
    }
    
    public void edgeDetect() {
	float[] elements = { 0.0f, -1.0f, 0.0f,
                            -1.0f, 4.0f, -1.0f,
                             0.0f, -1.0f, 0.0f };
        convolve(elements);
    }
    
    public void accentue(){
        
    }
    
    @Override
    public String toString(){
        return this.nom;
    }
}


